﻿using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationParts;

namespace Huasky.MyWrod.Common.Util;

public static class DIHelper
{
	public static Assembly[] GetAssemblies()
	{
		var manager = new ApplicationPartManager();

		var method = manager.GetType()
		                    .GetMethod("PopulateDefaultParts",
			                     BindingFlags.NonPublic | BindingFlags.Instance);


		//加载入口程序集的依赖项树中的所有非官方包的依赖程序集
		var assembly = Assembly.GetEntryAssembly().FullName;
        method.Invoke(manager, [assembly]);

		return manager.ApplicationParts.OfType<AssemblyPart>().Select(i => i.Assembly).ToArray();
	}

	//https://github.com/dotnet/aspnetcore/blob/c85baf8db0c72ae8e68643029d514b2e737c9fae/src/Mvc/Mvc.Core/src/ApplicationParts/ApplicationPartManager.cs

	//https://www.cnblogs.com/oldli/p/10945137.html


	public static (Type, T)[] LoadDiInfo<T>(Assembly[] assemblies) where T : Attribute
	{
		var query = from assembly in assemblies
		            from type in assembly.GetTypes()
		            let attribute = type.GetCustomAttribute<T>()
		            where attribute != null
		            select (type, attribute);

		return query.ToArray();
	}


	public static Type[] GetTypes<T>(Assembly[] assemblies)
	{
		var targetType = typeof(T);
		var query = from assembly in assemblies
		            from type in assembly.GetTypes()
		            where targetType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract
		            select type;

		return query.ToArray();
	}

	/// <summary>
	/// 创建类型T的子类的所有对象（）
	/// </summary>
	public static T[] CreateAll<T>()
	{
		var types = GetTypes<T>(GetAssemblies());
		return types.Select(t => (T)Activator.CreateInstance(t)).ToArray();
	}
}